#include <iostream>
#include <string>

#include "cpp-httplib/httplib.h"

#include "add_contacts.pb.h"

#include "contacts_exception.h"

// cpp-httplib test
// int main()
// {
//     httplib::Client cli("101.42.54.157", 8081);

//     httplib::Result res1 = cli.Post("/test-post");
//     if (res1->status == 200)
//         std::cout << "调用post成功" << std::endl;

//     httplib::Result res2 = cli.Get("/test-get");
//     if (res2->status == 200)
//         std::cout << "调用get成功" << std::endl;

//     return 0;
// }


int menu()
{
    std::cout << "-----------------------------------" << std::endl;
    std::cout << "-----1.新增联系人  2.删除联系人-----" << std::endl;
    std::cout << "-----3.搜索联系人  4.查看联系人-----" << std::endl;
    std::cout << "-----         0.退出          -----" << std::endl;
    std::cout << "-----------------------------------" << std::endl;
    std::cout << "请输入选择: ";
    int choice;
    std::cin >> choice;
    std::cin.ignore(256, '\n');
    return choice;
}

void BuildRequest(add_contacts::AddContactsRequest& req)
{
    std::cout << "-------------新增联系人------------" << std::endl;
    std::cout << "联系人姓名: ";
    std::string str;
    std::getline(std::cin, str);
    req.set_name(str);
    
    std::cout << "联系人年龄: ";
    int age = 0;
    std::cin >> age;
    req.set_age(age);
    std::cin.ignore(256, '\n');
    
    for (size_t i = 1; true; ++i)
    {
        std::cout << "联系人电话" << i << " (回车键停止输入): ";
        std::getline(std::cin, str);
        if (str.empty())
            break;
        add_contacts::AddContactsRequest_Phone* pPhone = req.add_phone();
        pPhone->set_number(str);
        std::cout << "请输入该电话类型(1.移动电话/2.固定电话): ";
        int type = 0;
        std::cin >> type;
        std::cin.ignore(256, '\n');
        switch (type)
        {
        case 1:
            pPhone->set_type(add_contacts::AddContactsRequest_Phone_PhoneType::AddContactsRequest_Phone_PhoneType_MOBLE_PHONE);
            break;
        case 2:
            pPhone->set_type(add_contacts::AddContactsRequest_Phone_PhoneType::AddContactsRequest_Phone_PhoneType_TLELPHONE);
            break;
        default:
            break;
        }
    }
}

void AddContacts()
{
    // 构造request
    add_contacts::AddContactsRequest req;
    BuildRequest(req);

    // 序列化request
    std::string req_str;
    if (!req.SerializeToString(&req_str))
        throw ContactsException("add contacts serialize request err");

    // 发送请求
    httplib::Client cli("101.42.54.157", 8081);
    httplib::Result res = cli.Post("/contacts/add", req_str, " application/protobuf");
    if (!res)
    {
        std::string err = "add contacts /contacts/add link err ";
        err.append(httplib::to_string(res.error()));
        throw ContactsException(err);
    }
    if (res->status != 200)
    {
        std::string err = "add contacts /contacts/add response err ";
        err += std::to_string(res->status);
        err += ' ';
        err.append(httplib::to_string(res.error()));
        throw ContactsException(err);
    }

    // 反序列化response
    add_contacts::AddContactsResponse resp;
    if (!resp.ParseFromString(res->body))
        throw ContactsException("add contacts parser err");
    if (!resp.success())
        throw ContactsException("add contacts result err");
    
    std::cout << "新增联系人成功 uid: ";
    std::cout << resp.uid() << std::endl;
}

int main()
{
    enum Option
    {
        OPTION_QUIT = 0,
        OPTION_ADD,
        OPTION_DEL,
        OPTION_FIND_ONE,
        OPTION_FIND_ALL
    };

    int choice = 0;
    do
    {
        choice = menu();
        try
        {
            switch (choice)
            {
            case OPTION_ADD:
                AddContacts();
                break;
            case OPTION_DEL:
                std::cout << "暂未提供该服务" << std::endl;
                break;
            case OPTION_FIND_ONE:
                std::cout << "暂未提供该服务" << std::endl;
                break;
            case OPTION_FIND_ALL:
                std::cout << "暂未提供该服务" << std::endl;
                break;
            case OPTION_QUIT:
                std::cout << "退出" << std::endl;
                break;
            default:
                std::cout << "选择错误" << std::endl;
                break;
            }
        }
        catch(const ContactsException& e)
        {
            std::cout << e.what() << std::endl;
        }
        
    } while (choice);
    
    return 0;
}